//using System;
//using System.IO;
//using System.ServiceModel;
//using System.Collections.Generic;
//using System.Text;
//using System.Diagnostics;
//using System.ServiceModel.Channels;
//using System.ServiceModel.Description;
//using System.Configuration;
//using System.Data.SqlClient;
//using System.Data;
//using System.Data.SqlTypes;
//using System.Reflection;
//using System.Xml;
//using Microsoft.MSE.Catalog.Contracts;
//using Microsoft.MSE.Catalog.Contracts.Services;
//using Microsoft.MSE.Catalog.Module;
//using System.Threading;
//using System.Runtime.Serialization;


//namespace Microsoft.MSE.Catalog.Services
//{

//    public class WCFCatalogSvcHost {

//        public static ServiceHost serviceHost = null;
//        private static SqlConnection sConn;
//        private static string sNotificationAddress = null;
//        private static XmlElement sNotificationBindingXml = null;
//        private static bool m_CancelStartup = false;

//        #region Service Control Methods
//        public static event EventHandler<StartServiceCompletedEventArgs> StartServiceCompleted;
//        protected static void OnStartServiceCompleted(StartServiceCompletedEventArgs e)
//        {
//            try
//            {
//                if (StartServiceCompleted != null)
//                {
//                    StartServiceCompleted(null, e);
//                }
//            }
//            catch { }
//        }
//        private delegate void StartServiceAsyncHandler(int retryInterval, int retryAttempts);
//        public static void StartServiceAsync()
//        {
//            m_CancelStartup = false;
//            Configurator.ReadConfig();

//            int delay = Configurator.svcConfig.StartupRetryInterval;
//            int attempts = Configurator.svcConfig.StartupRetryAttempts;
//            StartServiceAsyncHandler hnd = new StartServiceAsyncHandler(InnerStartService);
//            hnd.BeginInvoke(delay, attempts, delegate(IAsyncResult ar)
//            {
//                StartServiceCompletedEventArgs args = null;
//                try
//                {
//                    StartServiceAsyncHandler state = ar.AsyncState as StartServiceAsyncHandler;
//                    if (state != null)
//                        state.EndInvoke(ar);
//                    args = new StartServiceCompletedEventArgs(null, m_CancelStartup, null);
//                }
//                catch (System.Exception ex)
//                {
//                    args = new StartServiceCompletedEventArgs(ex, m_CancelStartup, null);
//                }
//                OnStartServiceCompleted(args);

//            }, hnd);
//        }
//        public static void StartService(){
//            m_CancelStartup = false;
//            Configurator.ReadConfig();

//            InnerStartService(0, 0);
//        }
//        private static void InnerStartService(int retryInterval, int retryAttempts) {

//            sConn = new SqlConnection(Configurator.svcConfig.DBConnString);

//            //if we can't connect to the repository, we are finished
//            if (!TryConnectToRepository(retryInterval, retryAttempts))
//            {
//                throw new ApplicationException("Could not establish connection to the Repository.");
//            }

//            WCFCatalogSvc catalogSvc = new WCFCatalogSvc(Configurator.svcConfig.baseAddress);
//            serviceHost = new ServiceHost(catalogSvc, Configurator.svcConfig.baseAddress);

//            ServiceMetadataBehavior bv = new ServiceMetadataBehavior();
//            bv.HttpGetEnabled = true;
//            serviceHost.Description.Behaviors.Add(bv);

//            foreach (ServiceEndpointElement endpoint in Configurator.svcConfig.serviceEndpoints) {
//                Binding binding = null;
//                Type contract = null;
//                binding = BindingHelper.DeserializeBinding((XmlElement)endpoint.bindingXml);
//                if (endpoint.address.AbsoluteUri.EndsWith("/mex"))
//                {
//                    contract = typeof(IMetadataExchange);
//                }
//                else if (endpoint.address.AbsoluteUri.EndsWith("/NotificationService"))
//                {
//                    contract = typeof(IChangeNotificationService);
//                    sNotificationAddress = endpoint.address.AbsoluteUri;
//                    sNotificationBindingXml = endpoint.bindingXml;

//                    //store these for calling the notification service
//                    RepositoryChangeManager.NotificationServiceAddress = sNotificationAddress;
//                    RepositoryChangeManager.NotificationServiceBinding = (XmlElement)endpoint.bindingXml;
//                }
//                else
//                {
//                    contract = typeof(IServiceModel);
//                    //if (binding is BasicHttpBinding)
//                    //    sNotificationAddress = endpoint.address.AbsoluteUri;
//                }
                               
//                TraceHelper.TraceInformation(SC.ComponentName + " adding endpoint address " + endpoint.address + " over " + endpoint.bindingXml.FirstChild.Name);
//                binding.ReceiveTimeout = new TimeSpan(1, 0, 0, 0, 0);  //TODO: Look at this
//                serviceHost.AddServiceEndpoint(contract,binding,endpoint.address);
//            }


//            ServiceDebugBehavior sdbbv = null;
//            foreach (object o in serviceHost.Description.Behaviors) {
//                if (o is ServiceDebugBehavior) sdbbv = o as ServiceDebugBehavior;
//            }

//            if (sdbbv == null) {
//                sdbbv = new ServiceDebugBehavior();
//                serviceHost.Description.Behaviors.Add(sdbbv);
//            }


//            sdbbv.HttpHelpPageEnabled = true;

//            if (Configurator.svcConfig.DebugMode) {
//                sdbbv.IncludeExceptionDetailInFaults = true;
//            }

//            // Add ServiceThrottlingBehavior
//            ServiceThrottlingBehavior stb = SetupServiceCatalogThrottle(Configurator.svcConfig.serviceCatalogThrottle);
//            if (null != stb)
//            {
//                ServiceThrottlingBehavior stdStb = serviceHost.Description.Behaviors.Find<ServiceThrottlingBehavior>();
//                if (null != stdStb)
//                {
//                    serviceHost.Description.Behaviors.Remove<ServiceThrottlingBehavior>();
//                }
//                serviceHost.Description.Behaviors.Add(stb);
//            }


//            serviceHost.Open();

//            if (Configurator.svcConfig.RepositoryChangeMonitor.Enabled)
//            {
//                TimeSpan polling = TimeSpan.FromSeconds(Configurator.svcConfig.RepositoryChangeMonitor.PollingInterval);
//                TimeSpan expiration = TimeSpan.FromMinutes(Configurator.svcConfig.RepositoryChangeMonitor.MessageExpiration);
//                RepositoryChangeManager.StartMonitor(polling, expiration);
//                TraceHelper.TraceInformation("Repository Change Monitoring is enabled.");
//            }
//            else
//            {
//                TraceHelper.TraceInformation("Repository Change Monitoring is disabled.");
//            }

//            //RegisterForEvent(DBEvents.EndpointsUpdated);
//            //RegisterForEvent(DBEvents.EndpointPolicyUpdated);
//            //RegisterForEvent(DBEvents.ServiceDefinitionUpdated);
//            //RegisterForEvent(DBEvents.ServicePolicyUpdated);
//            //RegisterForEvent(DBEvents.OperationsUpdated);
//            //RegisterForEvent(DBEvents.RuntimeServersUpdated);
//            //RegisterForEvent(DBEvents.EndpointOpAssociationUpdated);
//            //RegisterForEvent(DBEvents.EndpointOpPublicationUpdated);
//            //RegisterForEvent(DBEvents.RuntimeServersBindingUpdated);
//        }

//        public static void StopService() {
//            m_CancelStartup = true;
//            RepositoryChangeManager.StopMonitor();

//            //DeregisterForEvent(DBEvents.EndpointsUpdated);
//            //DeregisterForEvent(DBEvents.EndpointPolicyUpdated);
//            //DeregisterForEvent(DBEvents.ServiceDefinitionUpdated);
//            //DeregisterForEvent(DBEvents.ServicePolicyUpdated);
//            //DeregisterForEvent(DBEvents.OperationsUpdated);
//            //DeregisterForEvent(DBEvents.RuntimeServersUpdated);
//            //DeregisterForEvent(DBEvents.EndpointOpAssociationUpdated);
//            //DeregisterForEvent(DBEvents.EndpointOpPublicationUpdated);
//            //DeregisterForEvent(DBEvents.RuntimeServersBindingUpdated);

//            if (serviceHost != null) {
//                if (serviceHost.State != CommunicationState.Closed) serviceHost.Close();
//            }

//        }
//        #endregion

//        private static bool TryConnectToRepository(int retryInterval, int retryAttempts)
//        {
//            bool result = false;
//            bool autoclose = false;

//            if (sConn.State == ConnectionState.Closed)
//                autoclose = true;

//            //attempts = 1 + # of retries configured. 0 retries = 1 attempt
//            int attempts = retryAttempts <= 0 ? 1 : retryAttempts + 1;

//            while (!m_CancelStartup && attempts-- >= 0)
//            {
//                try
//                {
//                    sConn.Open();
//                    result = true;
//                    break;
//                }
//                catch (System.Exception ex)
//                {
//                    TraceHelper.TraceError("Unable to connect to repository. Exception: " + ex.Message);
//                }

//                //stop if there is no delay specified (only try once), or we have run out of attempts
//                if (retryInterval <= 0 || attempts <= 0)
//                {
//                    TraceHelper.TraceError("MSE Catalog could not connect to Repository.  No further attempts will be made.");
//                    break;
//                }

//                TraceHelper.TraceInformation("MSE Catalog will attempt to connect to Respository in {0} seconds. {1} attempt(s) remaining.", retryInterval, attempts);

//                //configuration value is in seconds, convert to msec for thread sleep.
//                System.Threading.Thread.Sleep(retryInterval * 1000);

//            }
            
//            if (result && autoclose)
//                sConn.Close();
         
//            return result;
//        }

//        private static ServiceThrottlingBehavior SetupServiceCatalogThrottle(ServiceCatalogThrottle serviceCatalogThrottle)
//        {
//            ServiceThrottlingBehavior stb = new ServiceThrottlingBehavior();
//            stb.MaxConcurrentCalls = 0 == serviceCatalogThrottle.MaxConcurrentCalls ? 100 : serviceCatalogThrottle.MaxConcurrentCalls;
//            stb.MaxConcurrentSessions = 0 == serviceCatalogThrottle.MaxConcurrentSessions ? 100 : serviceCatalogThrottle.MaxConcurrentSessions;
//            stb.MaxConcurrentInstances = 0 == serviceCatalogThrottle.MaxConcurrentInstances ? Int32.MaxValue : serviceCatalogThrottle.MaxConcurrentInstances;
//            return stb;
//        }

//        #region Depricated Event Registration
//        //private static void RegisterForEvent(DBEvents dbEvent)
//        //{
//        //    if (string.IsNullOrEmpty(sNotificationAddress))
//        //    {
//        //        TraceHelper.TraceError("Failed to register with CatalogDB for Event Notification - No BasicHTTPBinding specified");
//        //        return;
//        //    }

//        //    bool autoclose = false;
//        //    try
//        //    {
//        //        if (sConn.State == ConnectionState.Closed)
//        //        {
//        //            autoclose = true;
//        //            sConn.Open();
//        //        }

//        //        using (SqlCommand cmd = new SqlCommand("[ServiceEngine].[SubscribeToEvent]", sConn))
//        //        {
//        //            SqlParameter pEventname = new SqlParameter("@Eventname", SqlDbType.VarChar, 100);
//        //            SqlParameter pCallbackURI = new SqlParameter("@CallbackURI", SqlDbType.VarChar, 200);
//        //            SqlParameter pExpires = new SqlParameter("@Expires", SqlDbType.DateTime);
//        //            pExpires.Direction = ParameterDirection.Output;

//        //            cmd.CommandType = CommandType.StoredProcedure;
//        //            pEventname.Value = Enum.GetName(typeof(DBEvents), dbEvent);
//        //            pCallbackURI.Value = sNotificationAddress;
//        //            cmd.Parameters.Add(pEventname);
//        //            cmd.Parameters.Add(pCallbackURI);
//        //            cmd.Parameters.Add(pExpires);

//        //            cmd.ExecuteNonQuery();

//        //            if (!(((SqlDateTime)pExpires.SqlValue).IsNull))
//        //            {

//        //                string expires = ((DateTime)pExpires.Value).ToString();

//        //            }
//        //            else
//        //            {
//        //                TraceHelper.TraceError("Failed to register with CatalogDB for Event Notification - Response from CatalogDB was null expiration");
//        //            }
//        //        }
//        //    }
//        //    finally
//        //    {
//        //        if (autoclose) sConn.Close();
//        //    }

//        //}

//        //private static void DeregisterForEvent(DBEvents dbEvent)
//        //{
//        //    if (string.IsNullOrEmpty(sNotificationAddress))
//        //    {
//        //        return;
//        //    }

//        //    bool autoclose = false;
//        //    try
//        //    {
//        //        if (sConn.State == ConnectionState.Closed)
//        //        {
//        //            autoclose = true;
//        //            sConn.Open();
//        //        }
//        //        using (SqlCommand cmd = new SqlCommand("[ServiceEngine].[UnsubscribeFromEvent]", sConn))
//        //        {
//        //            SqlParameter pEventname = new SqlParameter("@Eventname", SqlDbType.VarChar, 100);
//        //            SqlParameter pCallbackURI = new SqlParameter("@CallbackURI", SqlDbType.VarChar, 200);

//        //            cmd.CommandType = CommandType.StoredProcedure;
//        //            pEventname.Value = Enum.GetName(typeof(DBEvents), dbEvent);
//        //            pCallbackURI.Value = sNotificationAddress;
//        //            cmd.Parameters.Add(pEventname);
//        //            cmd.Parameters.Add(pCallbackURI);

//        //            cmd.ExecuteNonQuery();
//        //        }
//        //    }
//        //    finally
//        //    {
//        //        if (autoclose) sConn.Close();
//        //    }

//        //}
//        #endregion

//    }
//}
